#include "../logs/log.h"
#include <fstream>

void util_test()
{
    std::cout << logs::util::Date::now() << std::endl;
    logs::util::File::createDirectory(logs::util::File::path("./abc/def/text.cc"));
}

void level_test()
{
    std::cout << logs::LogLevel::tostring(logs::LogLevel::value::UNKNOW) << std::endl;
    std::cout << logs::LogLevel::tostring(logs::LogLevel::value::DEBUG) << std::endl;
    std::cout << logs::LogLevel::tostring(logs::LogLevel::value::INFO) << std::endl;
    std::cout << logs::LogLevel::tostring(logs::LogLevel::value::WARN) << std::endl;
    std::cout << logs::LogLevel::tostring(logs::LogLevel::value::WARN) << std::endl;
    std::cout << logs::LogLevel::tostring(logs::LogLevel::value::FATAL) << std::endl;
    std::cout << logs::LogLevel::tostring(logs::LogLevel::value::OFF) << std::endl;
}

void formatter_test()
{
    logs::LogMsg msg("root", "test.cc", 52, logs::LogLevel::value::DEBUG, "hello world");
    logs::Formatter format("abc%%g%ggggg%g%g%g[%d{%H:%M:%S}][%t][%p][%c][%f:%l] %m%n");
    std::cout << format.format(msg) << std::endl;
}

void Sink_test()
{
    logs::LogMsg msg("root", "test.cc", 32, logs::LogLevel::value::DEBUG, "hello world");
    logs::Formatter format("[%d{%H:%M:%S}][%t][%p][%c][%f:%l] %m%n");
    std::string str = format.format(msg);
    logs::SinkFactory sf;
    logs::LogSink::ptr ptr1 = sf.create<logs::StdoutSink>();
    logs::LogSink::ptr ptr2 = sf.create<logs::FileSink>("./test.log");
    logs::LogSink::ptr ptr3 = sf.create<logs::RollSink>("./logs/", 1024 * 1024);

    // ptr1->log(str.c_str(), str.size());
    // ptr2->log(str.c_str(), str.size());
    // ptr3->log(str.c_str(), str.size());

    size_t cur_size = 0;
    size_t count = 0;
    while (cur_size < 1024 * 1024 * 10)
    {
        count++;
        std::string tmp = str + std::to_string(count);
        ptr1->log(tmp.c_str(), tmp.size());
        ptr2->log(tmp.c_str(), tmp.size());
        ptr3->log(tmp.c_str(), tmp.size());
        cur_size += tmp.size();
        usleep(100);
    }
}

void syncLogger_test()
{
    std::string logger_name = "sync_logger";
    logs::LogLevel::value default_level = logs::LogLevel::value::DEBUG;
    logs::Formatter::ptr formatter(new logs::Formatter("[%d{%H:%M:%S}[%c][%f:%l][%p]%T%m%n"));
    logs::LogSink::ptr stdout_lsp = logs::SinkFactory::create<logs::StdoutSink>();
    logs::LogSink::ptr file_lsp = logs::SinkFactory::create<logs::FileSink>("./logfile/test.log");
    logs::LogSink::ptr roll_lsp = logs::SinkFactory::create<logs::RollSink>("./logfile/roll-", 1024 * 1024);
    std::vector<logs::LogSink::ptr> sinks = {stdout_lsp, file_lsp, roll_lsp};
    logs::Logger::ptr logger(new logs::SyncLogger(logger_name, default_level, formatter, sinks));

    logger->debug(__FILE__, __LINE__, "%s", "测试日志");
    logger->info(__FILE__, __LINE__, "%s", "测试日志");
    logger->warn(__FILE__, __LINE__, "%s", "测试日志");
    logger->error(__FILE__, __LINE__, "%s", "测试日志");
    logger->fatal(__FILE__, __LINE__, "%s", "测试日志");
    size_t count = 0, cursize = 0;
    while (cursize < 1024 * 1024 * 10)
    {
        logger->fatal(__FILE__, __LINE__, "测试日志-%d", count++);
        cursize += 20;
    }
}

void build_sync_test()
{
    std::unique_ptr<logs::LoggerBuilder> builder(new logs::LocalLoggerBuilder());
    builder->buildLoggerName("sync_logger");
    builder->buildLoggerType(logs::LoggerType::LOGGER_SYNC);
    builder->buildFormatter("%m%n");
    builder->buildSink<logs::StdoutSink>();
    builder->buildSink<logs::FileSink>("./logfile/test.log");
    builder->buildSink<logs::RollSink>("./logfile/roll-", 1024 * 1024);
    logs::Logger::ptr logger = builder->build();

    logger->debug(__FILE__, __LINE__, "%s", "测试日志");
    logger->info(__FILE__, __LINE__, "%s", "测试日志");
    logger->warn(__FILE__, __LINE__, "%s", "测试日志");
    logger->error(__FILE__, __LINE__, "%s", "测试日志");
    logger->fatal(__FILE__, __LINE__, "%s", "测试日志");
    size_t count = 0, cursize = 0;
    while (cursize < 1024 * 1024 * 10)
    {
        logger->fatal(__FILE__, __LINE__, "测试日志-%d", count++);
        cursize += 20;
    }
}

void buffer_test()
{
    std::ifstream ifs("./logger.hpp", std::ios::binary | std::ios::in);
    ifs.seekg(0, std::ios::end);
    size_t fsize = ifs.tellg();
    ifs.seekg(0, std::ios::beg);
    std::string body;
    body.resize(fsize);
    ifs.read(&body[0], fsize);

    logs::Buffer buffer;
    for (int i = 0; i < body.size(); i++)
    {
        buffer.push(body.c_str() + i, 1);
    }
    ifs.close();

    std::ofstream ofs("./tmp.txt", std::ios::binary | std::ios::out);
    size_t size = buffer.readAbleSize();
    for (int i = 0; i < size; i++)
    {
        ofs.write(buffer.begin(), 1);
        buffer.moveReader(1);
    }
    ofs.close();
}

void build_async_test()
{
    std::unique_ptr<logs::LoggerBuilder> builder(new logs::LocalLoggerBuilder());
    builder->buildLoggerName("async_logger");
    builder->buildLoggerLevel(logs::LogLevel::value::DEBUG);
    builder->buildFormatter("%m%n");
    builder->buildLoggerType(logs::LoggerType::LOGGER_ASYNC);
    builder->buildSink<logs::FileSink>("./logfile/async.log");
    builder->buildSink<logs::StdoutSink>();
    logs::Logger::ptr logger = builder->build();

    logger->debug(__FILE__, __LINE__, "%s", "测试日志");
    logger->info(__FILE__, __LINE__, "%s", "测试日志");
    logger->warn(__FILE__, __LINE__, "%s", "测试日志");
    logger->error(__FILE__, __LINE__, "%s", "测试日志");
    logger->fatal(__FILE__, __LINE__, "%s", "测试日志");
    size_t count = 0, cursize = 0;
    while (cursize < 1024 * 1024 * 10)
    {
        logger->fatal(__FILE__, __LINE__, "测试日志-%d", count++);
        cursize += 20;
    }
}

void loggerMannger_test()
{
    std::unique_ptr<logs::LoggerBuilder> builder(new logs::GlobalLoggerBuilder());
    builder->buildLoggerName("async_logger");
    builder->buildFormatter("%m%n");
    builder->buildLoggerLevel(logs::LogLevel::value::DEBUG);
    builder->buildLoggerType(logs::LoggerType::LOGGER_ASYNC);
    builder->buildSink<logs::FileSink>("./logfile/async.log");
    builder->buildSink<logs::StdoutSink>();
    builder->build();

    logs::Logger::ptr logger = logs::LoggerManager::getInstance().getLogger("async_logger");
    logger->debug(__FILE__, __LINE__, "%s", "测试日志");
    logger->info(__FILE__, __LINE__, "%s", "测试日志");
    logger->warn(__FILE__, __LINE__, "%s", "测试日志");
    logger->error(__FILE__, __LINE__, "%s", "测试日志");
    logger->fatal(__FILE__, __LINE__, "%s", "测试日志");
    size_t count = 0;
    while (count < 500000)
    {
        logger->fatal(__FILE__, __LINE__, "测试日志-%d", count++);
    }
}

void log_test()
{
    std::unique_ptr<logs::LoggerBuilder> builder(new logs::GlobalLoggerBuilder());
    builder->buildLoggerName("async_logger");
    builder->buildFormatter("[%c][%f:%l]%m%n");
    builder->buildLoggerLevel(logs::LogLevel::value::DEBUG);
    builder->buildLoggerType(logs::LoggerType::LOGGER_ASYNC);
    builder->buildSink<logs::FileSink>("./logfile/async.log");
    builder->buildSink<logs::StdoutSink>();
    builder->build();

    logs::Logger::ptr logger = logs::LoggerManager::getInstance().getLogger("async_logger");
    logger->debug("%s", "测试日志");
    logger->info("%s", "测试日志");
    logger->warn("%s", "测试日志");
    logger->error("%s", "测试日志");
    logger->fatal("%s", "测试日志");
    size_t count = 0;
    while (count < 500000)
    {
        logger->fatal("测试日志-%d", count++);
    }
}

/*最终使用案例*/
void root_test()
{
    DEBUG("%s", "测试日志");
    INFO("%s", "测试日志");
    WARN("%s", "测试日志");
    ERROR("%s", "测试日志");
    FATAL("%s", "测试日志");
    size_t count = 0;
    while (count < 500000)
    {
        FATAL("测试日志-%d", count++);
    }
}

int main()
{
    root_test();
    return 0;
}